Promise = require 'bluebird'
http = require 'http'

config = require './config'
log = require './log'
error = require './error'

server = null

gCatchError = (next)->
    errorCatcher = @route.info?.errorCatcher
    if errorCatcher
        yield errorCatcher.call(this, next)
    else
        try
            yield next
        catch e
            if e instanceof error.Error401
                @status = 401
                if @route.info?.isPage
                    @redirect 'sign-in'
                else
                    @body = e.describe()
            else if e instanceof error.Error403
                @status = 403
                if @route.info?.isPage
                    @render '403'
                else
                    @body = e.describe()
            else if e instanceof error.UserError
                @status = 400
                if @route.info?.isPage
                    @render '400'
                else
                    @body = e.describe()
            else
                @status = 500
                log.system.error e, e.message, 'catch all'
                if @route.info?.isPage
                    @render '500'

exports.init = (extensions, afterClose)->
    koa = require 'koa'
    app = koa()
    app.keys = [config.cookieKey]
    app.proxy = true

    # 注册路由

    mainRouteRules = require('./routerRules')
    mainRouteRules.addRouteRules()
    for e in extensions
        e.addRouteRules() if e.addRouteRules

    # 初始化权限选项列表
    permissions = require('./meta/SystemMeta').permissions
    permissions.length = 0
    for key, p of mainRouteRules.rps
        permissions.push {name: p, label: p}

    router = require './router'
    router.refresh()

    # 中间件栈

    app.use router.parseRoute

    app.use(require('./jade').jade.middleware)

    app.use gCatchError # 匹配路由的过程不需要拦截错误

    ac = require('./http/AccessController')
    app.use ac.gIdentifyUser
    app.use ac.gControlAccess

    # 控制访问之后再解析正文
    koaBody = require 'koa-body'
    formidableConfig = {uploadDir: config.uploadPath, keepExtensions: true, maxFieldsSize: config.httpBodyMaxFieldsSize}
    app.use(koaBody(multipart: true, formidable: formidableConfig))

    app.use router.handleRoute # 开始处理路由

    server = http.createServer(app.callback())
    exports.server = server

    server.on 'error', (err) -> log.system.error err, 'Error on server!'
    server.on 'close', -> afterClose()

    enableDestroy = require 'server-destroy'
    enableDestroy(server)

exports.start = ->
    yield Promise.promisify(server.listen.bind(server))(config.serverPort)
    log.system.info 'Web Server Up!'

exports.stop = -> server?.destroy()